#include "bga/graphics/TextureCubeMap.h"

#include <SFML/Graphics/Image.hpp>

#include <iostream>

using namespace std;

GLenum cube_map_target[6] = {
    GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
    GL_TEXTURE_CUBE_MAP_POSITIVE_X,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Z
};

namespace bga
{

TextureCubeMap::TextureCubeMap() : TextureObject()
{
    this->target = GL_TEXTURE_CUBE_MAP;
    this->textureWidth = 0;
    this->textureHeight = 0;

    /// preconfiguration
    this->internalFormat = GL_RGBA;
    this->dataFormat = GL_RGBA;
    this->dataType = GL_UNSIGNED_BYTE;
    this->minFilter = GL_LINEAR;
    this->magFilter = GL_LINEAR;
    this->wrapS = GL_CLAMP_TO_EDGE;
    this->wrapT = GL_CLAMP_TO_EDGE;
}

TextureCubeMap::~TextureCubeMap()
{
}

void TextureCubeMap::setTextureWidth(unsigned int width)
{
    this->textureWidth = width;
}

unsigned int TextureCubeMap::getTextureWidth() const
{
    return this->textureWidth;
}

void TextureCubeMap::setTextureHeight(unsigned int height)
{
    this->textureHeight = height;
}

unsigned int TextureCubeMap::getTextureHeight() const
{
    return this->textureHeight;
}

void TextureCubeMap::allocateTexture()
{
    for (int i = 0; i < 6; i++)
    {
        glTexImage2D(cube_map_target[i], 0, this->internalFormat, this->textureWidth, this->textureHeight, 0, this->dataFormat, this->dataType, 0);
    }
    this->allocated = true;
}

void TextureCubeMap::loadImage()
{
    if (this->imageFilenameList.size() == 6 && !this->imageLoaded)
    {
        for (int i = 0; i < 6; i++)
        {
            sf::Image image;
            image.LoadFromFile(this->imageFilenameList[i]);

            if ( !this->allocated || this->textureWidth != image.GetWidth() || this->textureHeight != image.GetHeight() )
            {
                this->textureWidth = image.GetWidth();
                this->textureHeight =  image.GetHeight();
                allocateTexture();
            }

            /// load image data
            glTexSubImage2D(cube_map_target[i], 0, 0, 0, this->textureWidth, this->textureHeight, this->dataFormat, this->dataType, image.GetPixelsPtr());
            /// generate mipmap
            glGenerateMipmapEXT(target);

            this->imageLoaded = true;
        }
    }
    else
    {
        cout << "Error in TextureCubeMap::loadImage : cubemap must have 6 images." << endl;
    }
}

}

